package com.leju.common.dao.base;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

import com.leju.common.dao.impl.DAO;

/**
 * 此类必须jdk1.5或者以上版本才能够应用 此类中泛型M必须包含一个属性id，并且是唯一标示符
 * 
 * @author liuwei
 * 
 * @param <M>
 */
public class BaseDAO<M> extends DBHelper implements DAO<M> {
	public String currentTableName;

	/**
	 * 构造方法，根据泛型M获取要操作的数据库表，类名就是表明
	 * 
	 * @param context
	 */

	/**
	 * 构造方法，根据泛型M获取要操作的数据库表，类名就是表明
	 * 
	 * @param context
	 */
	public BaseDAO(Context context, int verson) {
		super(context, verson);
		currentTableName = getTableName();
		creatTable();
	}

	/**
	 * 构造方法，指定要操作的表明
	 * 
	 * @param context
	 * @param tableName
	 */

	/**
	 * 构造方法，指定要操作的表明
	 * 
	 * @param context
	 * @param tableName
	 */
	public BaseDAO(Context context, String tableName, int verson) {
		super(context, verson);
		currentTableName = tableName;
		creatTable();
	}

	/**
	 * 根据id删除一条数据
	 */
	@Override
	public void delete(Serializable id) {
		SQLiteDatabase db = getWritableDatabase();
		// db.delete(currentTableName, "id=?", new String[] { id.toString() });
		// db.close();
		StringBuffer sqStr = new StringBuffer("DELETE FROM [");
		sqStr.append(currentTableName).append("] ");
		sqStr.append("WHERE id= '");
		// Logger.e(id.toString());
		sqStr.append(id.toString()).append("'");
		// Logger.e(sqStr.toString());
		db.execSQL(sqStr.toString());
		db.close();

	}

	/**
	 * 根据传递的参数删除数据记录
	 */
	@Override
	public void deleteByParams(Map<String, String> map) {
		StringBuilder builder = new StringBuilder();
		builder.append("DELETE FROM [").append(currentTableName).append("] ");
		builder.append("WHERE ");

		for (Entry<String, String> entry : map.entrySet()) {
			builder.append(entry.getKey()).append("=").append("'").append(entry.getValue()).append("'").append(" AND ");
		}

		SQLiteDatabase db = getWritableDatabase();
		db.execSQL(builder.substring(0, builder.length() - 4));
		db.close();
	}

	/**
	 * 根据表名插入字段
	 * 
	 * @param tableName
	 */
	public void alterTable(String columnName) {
		SQLiteDatabase db = getWritableDatabase();
		StringBuffer sqStr = new StringBuffer("ALTER TABLE " + getTableName() + " ADD " + columnName + " VARCHAR(8)");
		db.execSQL(sqStr.toString());
		db.close();
	}

	/**
	 * 检查某表列是否存在
	 * 
	 * @param columnName
	 *            列名
	 * @return
	 */
	public boolean checkColumnExist(String columnName) {
		SQLiteDatabase db = getWritableDatabase();
		boolean result = false;
		Cursor cursor = null;
		try {
			cursor = db.rawQuery("SELECT * FROM " + getTableName() + " LIMIT 0", null);
			result = cursor != null && cursor.getColumnIndex(columnName) != -1;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != cursor && !cursor.isClosed()) {
				cursor.close();
			}
		}
		return result;
	}

	/**
	 * 查询表中所有信息
	 */
	@Override
	public List<M> findAll() {
		SQLiteDatabase db = getReadableDatabase();
		List<M> objList = new ArrayList<M>();

		Cursor cursor = db.rawQuery("select * from " + currentTableName, null);
		while (cursor.moveToNext()) {
			M m = getInstance();
			setProperties(m, cursor);
			objList.add(m);
		}
		db.close();
		cursor.close();
		return objList;
	}

	/**
	 * 按插入时的倒序查询表中的所有信息
	 * 
	 * @return
	 */
	public List<M> findAllByDesc() {
		SQLiteDatabase db = getReadableDatabase();
		List<M> objList = new ArrayList<M>();
		Cursor cursor = null;

		try {
			cursor = db.rawQuery("select * from " + currentTableName, null);

			for (cursor.moveToLast(); !cursor.isBeforeFirst(); cursor.moveToPrevious()) {
				M m = getInstance();
				setProperties(m, cursor);
				objList.add(m);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != cursor)
				cursor.close();
			if (null != db)
				db.close();
		}
		return objList;
	}

	/**
	 * 向表中插入一条数据
	 */
	@Override
	public void insert(M m) {
		try {
			SQLiteDatabase db = getWritableDatabase();
			ContentValues values = new ContentValues();
			setContentValue(m, values);
			db.insert(currentTableName, null, values);
			db.close();
		} catch (Exception e) {

			e.printStackTrace();
		}

	}

	/**
	 * 查询表中一共有多少条记录
	 */
	@Override
	public int totleCount() {
		SQLiteDatabase db = getReadableDatabase();

		Cursor cursor = db.rawQuery("select id from " + currentTableName, null);
		int num = 0;
		if (cursor != null) {
			// num = cursor.getColumnCount();
			num = cursor.getCount();

		}
		db.close();
		cursor.close();
		return num;

	}

	/**
	 * 更新一条数据
	 */
	@Override
	public void update(M m) {
		try {
			SQLiteDatabase db = getWritableDatabase();
			ContentValues values = new ContentValues();
			setContentValue(m, values);
			String id = "";
			try {
				Field field = m.getClass().getField("id");

				field.setAccessible(true);
				id = String.valueOf(field.get(m));
			} catch (Exception e) {
				e.printStackTrace();
			}
			db.update(currentTableName, values, "id=?", new String[] { id });
			db.close();
		} catch (Exception e) {

			e.printStackTrace();
		}

	}

	/**
	 * 根据ID查询一条记录，如果不存在，返回null
	 */
	@Override
	public M findById(Serializable id) {
		SQLiteDatabase db = getReadableDatabase();

		Cursor cursor = db.rawQuery("select * from " + currentTableName.toLowerCase() + " where id=?", new String[] { id.toString() });

		if (cursor.moveToFirst()) {
			M m = getInstance();
			setProperties(m, cursor);
			db.close();
			cursor.close();
			return m;
		}
		cursor.close();
		db.close();
		return null;
	}

	/**
	 * 指定字段以及字段的值 查询所有满足条件的数据
	 */
	@Override
	public ArrayList<M> findBySpecifiedValue(Serializable key, Serializable value) {
		ArrayList<M> objList = new ArrayList<M>();
		SQLiteDatabase db = getReadableDatabase();

		Cursor cursor = db.rawQuery(

		"select * from " + currentTableName.toLowerCase() + " where " + key.toString() + "=?", new String[] { value.toString() });

		if (cursor != null) {
			while (cursor.moveToNext()) {
				M m = getInstance();
				setProperties(m, cursor);
				objList.add(m);
			}
		}
		cursor.close();
		db.close();
		return objList;
	}
	
	/**
	 * 根据指定的字段查询数据
	 * 
	 * @param conditions
	 *            字段数组 必须和M的属性相一致
	 * @return
	 */
	public ArrayList<M> findBySpecifiedConditions(String[] conditions) {
		ArrayList<M> objList = new ArrayList<M>();
		SQLiteDatabase db = getReadableDatabase();
		StringBuffer buffer = new StringBuffer("select");

		int length = conditions.length;
		for (int i = 0; i < length; i++) {
			if (i != 0) {
				buffer.append(",");
			}
			buffer.append(" " + conditions[i]);
		}
		buffer.append(" from " + currentTableName);

		Cursor cursor = db.rawQuery(buffer.toString(), null);
		if (cursor != null) {
			while (cursor.moveToNext()) {
				M m = getInstance();
				setProperties(m, cursor);
				objList.add(m);
			}
		}
		cursor.close();
		db.close();
		return objList;
	}

	/**
	 * 利用反射，把泛型实例的属性以及对应的值以key-value的形式存放在ContentValues中，方便数据库的插入和更新
	 * 
	 * @param m
	 * @param values
	 */
	private void setContentValue(M m, ContentValues values) {
		try {

			Field[] fields = m.getClass().getFields();
			for (Field field : fields) {
				if (fieldsFilter(field)) {
					if (field.getType() == int.class) {
						values.put(field.getName(), (Integer) field.get(m));
					} else if (field.getType() == long.class) {
						values.put(field.getName(), (Long) field.get(m));
					} else if (field.getType() == short.class) {
						values.put(field.getName(), (Short) field.get(m));
					} else if (field.getType() == String.class) {
						values.put(field.getName(), (String) field.get(m));
					} else if (field.getType() == float.class) {
						values.put(field.getName(), (Float) field.get(m));
					} else if (field.getType() == double.class) {
						values.put(field.getName(), (Double) field.get(m));
					}
				}

			}
		} catch (Exception e) {

			e.printStackTrace();
		}
	}

	/**
	 * 判断属性是否和法，如果是static或者final的 返回false 表示不和法 ，过滤掉
	 * 
	 * @param field
	 * @return
	 */
	private boolean fieldsFilter(Field field) {
		if (field == null) {
			return false;
		}

		if (Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())) {
			return false;
		}
		return true;

	}

	/**
	 * 设置字段值
	 * 
	 * @param m
	 * @param cursor
	 */
	protected void setProperties(M m, Cursor cursor) {
		try {
			Field[] declaredFields = m.getClass().getFields();

			for (Field item : declaredFields) {

				if (fieldsFilter(item)) {

					item.setAccessible(true);
					setPropertyValueByType(m, item, cursor);
				}

			}
		} catch (Exception e) {

			e.printStackTrace();
		}
	}

	/**
	 * 创建数据库表
	 */
	protected synchronized void creatTable() {
		try {
			StringBuffer sb = new StringBuffer("create table if not exists ").append(currentTableName).append("(id text primary key");
			// "(id  integer primary key");
			Field[] declaredFields = getGenericClass().getFields();
			for (Field item : declaredFields) {
				String fileNameString = item.getName().toLowerCase();
				if (fieldsFilter(item) && !fileNameString.equals("id")) {
					sb.append("," + fileNameString);

				}

			}

			sb.append(");");
			SQLiteDatabase db = getWritableDatabase();
			db.execSQL(sb.toString());
			db.close();
		} catch (SecurityException e) {

			e.printStackTrace();
		} catch (SQLException e) {

			e.printStackTrace();
		}

	}

	/**
	 * 设置字段值，为对象的某一个属性设置值
	 * 
	 * @param m
	 * @param field
	 * @param cursor
	 * @throws Exception
	 */
	private void setPropertyValueByType(M m, Field field, Cursor cursor) throws Exception {
		Object newValue;
		String columnName = field.getName().toLowerCase();
		int columnIndex = cursor.getColumnIndex(columnName);
		// 如果cursor不包含field的属性，则返回
		if (columnIndex < 0) {
			return;
		}

		if (field.getType() == int.class) {

			newValue = cursor.getInt(columnIndex);
			field.set(m, (Integer) newValue);
			return;
		} else if (field.getType() == long.class) {
			newValue = cursor.getLong(columnIndex);
			field.set(m, (Long) newValue);
			return;
		} else if (field.getType() == short.class) {
			newValue = cursor.getShort(columnIndex);
			field.set(m, (Short) newValue);
			return;
		} else if (field.getType() == float.class) {
			newValue = cursor.getFloat(columnIndex);
			field.set(m, (Float) newValue);
			return;
		} else if (field.getType() == double.class) {
			newValue = cursor.getDouble(columnIndex);
			field.set(m, (Double) newValue);
			return;
		} else if (field.getType() == String.class) {
			newValue = cursor.getString(columnIndex);

			field.set(m, (String) newValue);
			return;
		} else {
			return;
		}
	}

	/**
	 * 获取当前的实体Bean的实例
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected M getInstance() {

		Class<?> t = getGenericClass();
		if (t != null) {
			try {
				return (M) t.newInstance();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return null;
	}

	protected Class<?> getGenericClass() {
		Type type = getClass().getGenericSuperclass();
		if (type instanceof ParameterizedType) {

			return (Class<?>) (((ParameterizedType) type).getActualTypeArguments()[0]);
		}
		return null;

	}

	/**
	 * 获取当前类要操作的数据库表
	 * 
	 * @return
	 */
	protected String getTableName() {
		String tableName = null;

		Class<?> cla = getGenericClass();
		tableName = cla.getSimpleName();
		return tableName;
	}

	/**
	 * 删除表中的所有数据
	 */
	@Override
	public boolean deleteAll() {
		StringBuffer buffer = new StringBuffer("delete from '");
		SQLiteDatabase db = getWritableDatabase();
		try {
			// 删除表数据
			buffer.append(currentTableName).append("';");
			db.execSQL(buffer.toString());
		} catch (SQLException e1) {
			db.close();
			e1.printStackTrace();
			return false;
		}
		try {
			// 删除key的自增长数据，当表中没有自增长字段是，这里将会出现异常
			buffer.delete(0, buffer.toString().length());
			db.execSQL("select * from sqlite_sequence;");

			buffer.append("update sqlite_sequence set seq=0 where name='").append(currentTableName).append("';");
			db.execSQL(buffer.toString());
		} catch (SQLException e) {
			db.close();
			e.printStackTrace();

		}
		if (db.isOpen()) {
			db.close();
		}

		return true;
	}

	/**
	 * 删除表
	 */
	public void dropTable() {
		SQLiteDatabase db = getWritableDatabase();

		String sql = "DROP TABLE IF EXISTS " + getTableName();
		db.execSQL(sql);
		db.close();
	}
}
